// Copyright (c) 2025 Zhou Yiyan
// Dynamic World Generation Library is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.

// Package worldgen provides core types and interfaces for dynamic world generation.
package worldgen

import "math/rand"

// GetTransitionProbability returns the natural transition probability between two tile types.
func GetTransitionProbability(from, to TileType) float64 {
	if transitions, exists := transitionMatrix[from]; exists {
		if prob, exists := transitions[to]; exists {
			return prob
		}
	}
	return 0.0 // Default: no natural transition
}

// ShouldTransition determines if a tile should transition based on neighbor influence.
func ShouldTransition(currentTile, neighborTile TileType, similarity float64, rng *rand.Rand) bool {
	if currentTile == neighborTile {
		return false // No need to transition to same type
	}

	baseProbability := GetTransitionProbability(neighborTile, currentTile)
	if baseProbability == 0.0 {
		return false // Physically impossible transition
	}

	// Adjust probability based on similarity coefficient
	adjustedProbability := baseProbability * similarity

	// Random chance based on adjusted probability
	return rng.Float64() < adjustedProbability
}

// BlendEdge blends the edges of a chunk with its neighbors.
func BlendEdge(chunk ChunkData, neighbors map[ChunkCoord]ChunkData, similarity float64, rng *rand.Rand) {
	for coord, neighborChunk := range neighbors {
		blendWithNeighbor(chunk, neighborChunk, coord, similarity, rng)
	}
}

// blendWithNeighbor blends the edge of this chunk with a specific neighbor.
func blendWithNeighbor(chunk, neighborChunk ChunkData, neighborCoord ChunkCoord, similarity float64, rng *rand.Rand) {
	// Determine which edge to blend based on relative coordinates
	// This is a simplified implementation - would need actual coordinate math
	// For MVP, we'll implement basic edge blending logic

	for y := 0; y < ChunkSize; y++ {
		for x := 0; x < ChunkSize; x++ {
			// Only process edge tiles
			if isEdgeTile(x, y) {
				// Get corresponding neighbor tile (simplified)
				neighborTile := getNeighborTile(neighborChunk, x, y, neighborCoord)

				if ShouldTransition(chunk[y][x], neighborTile, similarity, rng) {
					chunk[y][x] = neighborTile
				}
			}
		}
	}
}

// isEdgeTile checks if a tile is on the edge of the chunk.
func isEdgeTile(x, y int) bool {
	return x == 0 || x == ChunkSize-1 || y == 0 || y == ChunkSize-1
}

// getNeighborTile gets the corresponding tile from a neighbor chunk.
// This is a simplified implementation for MVP.
func getNeighborTile(neighborChunk ChunkData, x, y int, neighborCoord ChunkCoord) TileType {
	// For MVP, return a random tile from the neighbor chunk
	// In real implementation, would use proper coordinate mapping
	if len(neighborChunk) > 0 && len(neighborChunk[0]) > 0 {
		return neighborChunk[y%len(neighborChunk)][x%len(neighborChunk[0])]
	}
	return TileTypeEmpty
}
